﻿#include "VAOneXMLAdaptorSeaCavity.h"
#include "rapidxml.hpp"
#include <QFile>
#include <iostream>
#include <QDebug>
#include "FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITKAcousticsModel/FITKSEASubSysCavity.h"
#include "FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITKAcousticsPhysics/FITKAcousticsSpectraManager.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITKAcousticsModel/FITKAbstractSEAFace.h"

namespace IO
{
    bool VAOneXMLAdaptorSeaCavity::adaptR()
    {
        bool b = true;

        //指针检查
        if(nullptr == _node)
        {
            return false;
        }

        Acoustics::FITKAcousticsSEASubSysManager *dataManager = dynamic_cast<Acoustics::FITKAcousticsSEASubSysManager*>(_dataObj);
        if (nullptr == dataManager)
        {
            return false;
        }

        rapidxml::xml_node<char>* node = _node->first_node("Cavity");

        while (nullptr != node)
        {
            Acoustics::FITKSEASubSysCavity *data = new Acoustics::FITKSEASubSysCavity;

            readCell(node, data);

            dataManager->appendDataObj(data);

            node = node->next_sibling("Cavity");
        }

        // 返回操作是否成功
        return b;
    }

    bool VAOneXMLAdaptorSeaCavity::adaptW()
    {
        Acoustics::FITKAcousticsSEASubSysManager *dataManager = dynamic_cast<Acoustics::FITKAcousticsSEASubSysManager*>(_dataObj);

        if ((nullptr == dataManager) || (nullptr == _node))
        {
            return false;
        }

        // 获取列表
        QList<Acoustics::FITKAbstractSEASubSys*> list = dataManager->getSubSysByType(Acoustics::FITKAbstractSEASubSys::SEACavity);

        // 循环处理cavity
        for (auto data : list)
        {
            // 创建Cavity节点
            rapidxml::xml_node<char>* node = createNodeElement(_node, "Cavity");
            if (nullptr == node)
            {
                continue;
            }

            //单个节点信息写入
            writeCell((Acoustics::FITKSEASubSysCavity *)data, node);
        }

        // 返回操作是否成功
        return true;
    }

    void VAOneXMLAdaptorSeaCavity::readDamping(rapidxml::xml_node<char>* node, Acoustics::FITKSEASubSysCavity *data)
    {
        if ((nullptr == data) || (nullptr == node))
        {
            return;
        }

        bool bOK = true;

        //damping_method="2"
        int type = readIntAttribute(node, "damping_method", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read structural_damping failed";
            return;
        }

        //获取physis管理器
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (nullptr == phyMgr)
        {
            return;
        }

        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = phyMgr->getFITKAcousticsSpectraManager();
        if (nullptr == spectraMgr)
        {
            return;
        }

        int id = -1;
        if (0 == type)
        {
            //damping="1% loss factor"
            QString damp = readStrAttribute(node, "damping", &bOK);
            if (true != bOK)
            {
                qDebug()<<"read damping failed";
                return;
            }

            //将字符串信息转换成ojectid
            Acoustics::FITKAcousticsAbstractSpectra* spectraData = spectraMgr->getDataByName(damp);
            if (nullptr != spectraData)
            {
                id = spectraData->getDataObjectID();
            }
        }
        else if (1 == type)
        {
            //avgabsorption="1% absorption"
            QString str = readStrAttribute(node, "avgabsorption", &bOK);
            if (true != bOK)
            {
                qDebug()<<"read avgabsorption failed";
                return;
            }

            Acoustics::FITKAcousticsAbstractSpectra* spectraData = spectraMgr->getDataByName(str);
            if (nullptr != spectraData)
            {
                id = spectraData->getDataObjectID();
            }
        }
        else if (2 == type)
        {
            id = -1;
        }

        data->setDampingID(id);
    }

    void VAOneXMLAdaptorSeaCavity::readGeo(rapidxml::xml_node<char> *node, Acoustics::FITKSEASubSysCavity *data)
    {
        if ((nullptr == node) || (nullptr == data))
        {
            return;
        }

        bool bOK = true;

        //volume="80.7683"
        //surface_area="135.031"
        //perimeter="59.9006"
        //override_volume="true"
        //override_surface_area="true"
        //override_perimeter="true"
        double volume = -1;
        double surface_area = -1;
        double perimeter = -1;

        QString override_volume = readStrAttribute(node, "override_volume", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read override volume error";
            return;
        }

        //if (true == strToBool(override_volume))
        //{
        volume = readDoubleAttribute(node, "volume", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read volume error";
            return;
        }

        data->setVolume(volume);
        //}

        QString override_surface_area = readStrAttribute(node, "override_surface_area", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read override surface_area error";
            return;
        }

        if (true == strToBool(override_surface_area))
        {
            surface_area = readDoubleAttribute(node, "surface_area", &bOK);
            if (true != bOK)
            {
                qDebug()<<"read surface_area error";
                return;
            }

            data->setSurfaceArea(surface_area);
        }

        QString override_perimeter = readStrAttribute(node, "override_perimeter", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read override perimeter error";
            return;
        }

        if (true == strToBool(override_perimeter))
        {
            perimeter = readDoubleAttribute(node, "perimeter", &bOK);
            if (true != bOK)
            {
                qDebug()<<"read perimeter error";
                return;
            }

            data->setPerimeter(perimeter);
        }
    }

    void VAOneXMLAdaptorSeaCavity::readPress(rapidxml::xml_node<char> *node, Acoustics::FITKSEASubSysCavity *data)
    {
        if ((nullptr == node) || (nullptr == data))
        {
            return;
        }

        bool bOK = true;

        QString str = readStrAttribute(node, "include_in_matrix_solution", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read include_in_matrix_solution error";
            return;
        }
        data->setInSEAMatrixSolution(strToBool(str));

        //不做判断 字段可能不存在
        str = readStrAttribute(node, "ud_modal_density", &bOK);
        //data->setFlexureModelDensityState(false);
        int id = getModalDensityId(str);
        if (-1 != id)
        {
            data->setModalDensity(id);
        }
    }

    void VAOneXMLAdaptorSeaCavity::readCell(rapidxml::xml_node<char> *node, Acoustics::FITKSEASubSysCavity *data)
    {
        if ((nullptr == node) || (nullptr == data))
        {
            return;
        }
        bool bOK = true;

        //<Name>Cavity</Name>
        rapidxml::xml_node<char> * child = node->first_node("Name");
        if (nullptr != child)
        {
            QString name = readStrNodeValue(child, &bOK);
            if (true != bOK)
            {
                qDebug()<<"read cavity name error";
                return;
            }

            data->setDataObjectName(name);//名称可以为空，但是节点不能为空
        }

        //读取材料
        QString name = readStrAttribute(node, "fluid", &bOK);
        if (true != bOK)
        {
            qDebug()<<"read material name error";

            return;
        }

        data->setMaterialID(getMaterialObjectIdByName(name));

        //损耗数据
        readDamping(node, data);

        //几何信息
        readGeo(node, data);

        //压力信息
        readPress(node, data);

        //读取faceid信息
        child = node->first_node("FaceRef");
        while (nullptr != child)
        {
            int faceId = readIntAttribute(child, "face_id", &bOK);
            if (true != bOK)
            {
                qDebug()<<"Cavity Face id read error";
                return;
            }

            int objId = getFaceObjId(faceId);
            data->addFace(objId);

            child = child->next_sibling("FaceRef");
        }
    }

    void VAOneXMLAdaptorSeaCavity::writeDamping(Acoustics::FITKSEASubSysCavity *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        int dampMethod = 0;

        //获取physis管理器
        Acoustics::FITKAcousticsPhysics* phyMgr = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (nullptr == phyMgr) return;

        //获取频谱管理器
        Acoustics::FITKAcousticsSpectraManager* spectraMgr = phyMgr->getFITKAcousticsSpectraManager();
        if (nullptr == spectraMgr) return;

        int type = data->getDampingType();
        int id = data->getDampingID();
        QString dampname = "";
        if (Acoustics::FITKAcousticsAbstractSpectra::Damping == type)
        {
            //将ojectid转成字符串信息
            Acoustics::FITKAcousticsAbstractSpectra* spectraData = spectraMgr->getDataByID(id);

            if (nullptr != spectraData) dampname = spectraData->getDataObjectName();
            dampMethod = 0;
        }
        else if (Acoustics::FITKAcousticsAbstractSpectra::Absorption == type)
        {
            //avgabsorption="1% absorption"
            QString name = "";

            Acoustics::FITKAcousticsAbstractSpectra* spectraData = spectraMgr->getDataByID(id);
            if (nullptr != spectraData) name = spectraData->getDataObjectName();

            writeAttribute(node, "avgabsorption", name);
            dampMethod = 1;
        }
        else
        {
            dampMethod = 2;
        }

        //damping_method="2"
        writeAttribute(node, "damping", dampname);

        //几何
        writeGeo(data, node);

        //压力
        writePress(data, node);

        writeAttribute(node, "damping_method", dampMethod);
        writeAttribute(node, "use_connected_maj", "false");
    }

    void VAOneXMLAdaptorSeaCavity::writeGeo(Acoustics::FITKSEASubSysCavity *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        writeAttribute(node, "volume", data->getVolume());
        writeAttribute(node, "surface_area", data->getSurfaceArea());
        writeAttribute(node, "perimeter", data->getPerimeter());
        writeAttribute(node, "override_volume", boolToStr(data->isOverride(0)));
        writeAttribute(node, "override_surface_area", boolToStr(data->isOverride(1)));
        writeAttribute(node, "override_perimeter", boolToStr(data->isOverride(2)));
    }

    void VAOneXMLAdaptorSeaCavity::writePress(Acoustics::FITKSEASubSysCavity *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        int id = data->getModalDensity();
        if (-1 != id)
        {
            QString str = getModalDensityName(id);
            if (true != str.isEmpty())
            {
                // writeAttribute(node, "ud_modal_density", str);
                writeAttribute(node, "xsea_alias", getModalDensityName(id));
            }
        }
        else {
            writeAttribute(node, "xsea_alias", "");
        }
        writeAttribute(node, "include_in_matrix_solution", boolToStr(data->getInSEAMatrixSolution()));
        writeAttribute(node, "all_face_direction", "COMPUTE");
    }

    void VAOneXMLAdaptorSeaCavity::writeCell(Acoustics::FITKSEASubSysCavity *data, rapidxml::xml_node<char> *node)
    {
        if ((nullptr == node) || (nullptr == data)) return;

        //材料
        writeAttribute(node, "fluid", getMaterialObjectNameById(data->getMaterialID()));

        //损耗
        writeDamping(data, node);

        //<Name>cavity</Name>
        rapidxml::xml_node<char> * child = createNodeElement(node, "Name", data->getDataObjectName());
        if (nullptr == child)
        {
            qDebug() << "cavity name write failed";
            return;
        }

        //<Name>cavity</Name>
        rapidxml::xml_node<char> * noteChild = createNodeElement(node, "Note", "");
        if (nullptr == noteChild) return;

        //写faceid信息
        for (int i = 0; i < data->getFaceCount(); i++)
        {
            child = createNodeElement(node, "FaceRef");
            if (nullptr == child)
            {
                continue;
            }

            int faceId = data->getFaceID(i);
            writeAttribute(child, "face_id", faceId);
        }
    }
}
